package com.dingreading.cloud.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.DateUtil;
import com.dingreading.cloud.common.util.DescribeException;
import com.dingreading.cloud.common.util.EnumType;
import com.dingreading.cloud.common.util.KitUtil;
import com.dingreading.cloud.common.util.alipay.AliPayApi;
import com.dingreading.cloud.common.util.alipay.AlipayConfig;
import com.dingreading.cloud.common.util.wechat.AuthToken;
import com.dingreading.cloud.common.util.wechat.PayExtraUtil;
import com.dingreading.cloud.common.util.wechat.WxPayBusiness;
import com.dingreading.cloud.web.entity.CooperPayOrder;
import com.dingreading.cloud.web.service.CooperPayOrderService;
import com.dingreading.cloud.web.util.redis.RedisService;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;

@RefreshScope
@RestController
@RequestMapping("/front/cooperPayOrder/v3")
@Api(tags = "前端-叮叮合作费支付管理V3(合肥叮叮书房文化科技有限公司)")
public class FrontCooperPayOrderV3Controller {

    // 叮叮书房文化
    @Value("${wx.sf.appId}")
    private String shAppId;
    @Value("${wx.sf.appSecret}")
    private String shAppSecret;
    @Value("${wx.sf.mchId}")
    private String shMchId;
    @Value("${wx.sf.mchKey}")
    private String shMchKey;
    // 支付回调地址
    @Value("${payNotifyUrl}")
    private String notifyUrl;

    @Resource
    private CooperPayOrderService cooperPayOrderService;
    @Resource
    protected RedisService redisService;


    @ApiOperation(value = "微信获取openid接口")
    @PostMapping(value = "/getSfOpenId", produces = "application/json; charset=UTF-8")
    public R<Object> getSfOpenId(
            @ApiParam(value = "微信授权码") @RequestParam(value = "code") String code
    ) throws Exception {
        String redisKey = "authAccess_" + code;
        String redisAccessToken = (String) redisService.get(redisKey);

        AuthToken authToken = null;
        if (StringUtils.isNotEmpty(redisAccessToken)) {
            authToken = JSONObject.parseObject(redisAccessToken, AuthToken.class);
        } else {
            authToken = WxPayBusiness.Init().getAccessToken(code, shAppId, shAppSecret);

            // 缓存code获取的accessToken
            redisService.set(redisKey, JSONObject.toJSONString(authToken), 1800);
        }

        if (authToken != null) {
            if (authToken.getErrcode() == null)
                return R.ok(authToken.getOpenid());
            else
                return R.fail(authToken.getErrmsg());
        }
        return R.fail("获取微信openid失败");
    }

    @ApiOperation(value = "生成订单")
    @PostMapping(value = "/newOrder", produces = "application/json; charset=UTF-8")
    public R<Object> newOrder(
            @ApiParam(value = "客户姓名") @RequestParam(value = "userName") String userName,
            @ApiParam(value = "客户电话") @RequestParam(value = "userPhone") String userPhone,
            @ApiParam(value = "销售姓名") @RequestParam(value = "saleName") String saleName,
            @ApiParam(value = "收款项目名称") @RequestParam(value = "payName") String payName,
            @ApiParam(value = "金额") @RequestParam(value = "money") double money,
            @ApiParam(value = "备注") @RequestParam(value = "remark", required = false) String remark
    ) {
        if (StringUtils.isBlank(userName))
            return R.fail("请先输入客户姓名");
        if (StringUtils.isBlank(userPhone) || userPhone.length() != 11)
            return R.fail("请先输入客户电话");
        if (StringUtils.isBlank(saleName))
            return R.fail("请先输入销售姓名");
        if (StringUtils.isBlank(payName))
            return R.fail("请先输入收款项目名称");
        if (money <= 0)
            return R.fail("请先输入正确的收款金额");

        Date time = DateUtil.getNowDatetime();

        CooperPayOrder data = new CooperPayOrder();
        data.setCorpName("合肥叮叮书房文化科技有限公司");
        data.setUserName(userName.trim());
        data.setUserPhone(userPhone.trim());
        data.setSaleName(saleName.trim());
        data.setPayName(payName.trim());
        data.setRemark(remark.trim());
        data.setOrderUid(KitUtil.getUuid());
        data.setCode(KitUtil.getGoodsCode());
        data.setPayPrice(money);
        data.setBuyNum(1);
        data.setProjectType(EnumType.BalanceProject.CORP_PAY.getType());
        data.setProjectName(EnumType.BalanceProject.CORP_PAY.getName());
        data.setStatus(2);
        // 一小时后过期
        Date expireTime = DateUtil.addHours(time, 1);
        data.setExpireTime(expireTime);
        cooperPayOrderService.saveOrUpdate(data);
        if (null == data) return R.fail("生成订单失败");

        return R.ok(data.getOrderUid());
    }

    @ApiOperation(value = "获取订单信息")
    @PostMapping(value = "/getOrder", produces = "application/json; charset=UTF-8")
    public R<Object> getOrder(
            @ApiParam(value = "订单uid") @RequestParam(value = "orderUid") String orderUid
    ) {
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        if (null == form) return R.fail("订单获取失败");

        return R.ok(form);
    }

    @ApiOperation(value = "订单状态判断")
    @PostMapping(value = "/judgeOrderForm", produces = "application/json; charset=UTF-8")
    public R<Object> judgeOrderForm(
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        if (null == form) return R.fail("订单获取失败");
        if (form.getStatus().equals(0)) return R.fail("订单已被取消");
        if (form.getStatus().equals(1)) return R.fail("订单已被支付");
        if (form.getPayPrice() <= 0) return R.fail("订单的付款金额错误");
        if (DateUtil.getNowDatetime().getTime() > form.getExpireTime().getTime())
            return R.fail("订单有效已过期");

        return R.ok();
    }

    @ApiOperation(value = "微信付款二维码")
    @PostMapping(value = "/getWeChatQrCode", produces = "application/json; charset=UTF-8")
    public R<Object> getWeChatQrCode(
            HttpServletRequest request,
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);

        // 判断订单状态
        R<Object> r = judgeOrder(form);
        if (R.isError(r))
            return r;

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.WXPAY_QR.getType());

        // 微信付款二维码
        Map<String, String> map = Maps.newHashMap();
        map.put("OutTradeNo", code);
        map.put("body", form.getPayName());
        map.put("fee", String.valueOf(form.getPayPrice()));
        map.put("tradeType", EnumType.TradeType.WECHAT_NATIVE.getType());
        map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));
        // 获取统一下单后的参数
        try {
            R<Object> payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, shAppId, shAppSecret, shMchId, shMchKey, notifyUrl);
            return payR;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.fail("收银台-微信付款二维码，发起支付异常");
    }

    @ApiOperation(value = "微信付款公众号")
    @PostMapping(value = "/getWeChatJsapi", produces = "application/json; charset=UTF-8")
    public R<Object> getWeChatJsapi(
            HttpServletRequest request,
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid,
            @RequestParam(value = "openid") @ApiParam(value = "微信openid") String openid
    ) {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        // 判断订单状态
        R<Object> r = judgeOrder(form);
        if (R.isError(r))
            return r;

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.WXPAY_JSAPI.getType());

        // 微信付款二维码
        Map<String, String> map = Maps.newHashMap();
        map.put("openid", openid);
        map.put("OutTradeNo", code);
        map.put("body", form.getPayName());
        map.put("fee", String.valueOf(form.getPayPrice()));
        map.put("tradeType", EnumType.TradeType.WECHAT_JSAPI.getType());
        map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));
        // 获取统一下单后的参数
        try {
            R<Object> payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, shAppId, shAppSecret, shMchId, shMchKey, notifyUrl);
            return payR;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.fail("收银台-微信付款公众号，发起支付异常");
    }

    @ApiOperation(value = "微信付款H5支付")
    @PostMapping(value = "/getWeChatWap", produces = "application/json; charset=UTF-8")
    public R<Object> getWeChatWap(
            HttpServletRequest request,
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        // 判断订单状态
        R<Object> r = judgeOrder(form);
        if (R.isError(r))
            return r;

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.WXPAY_H5.getType());

        // 微信付款二维码
        Map<String, String> map = Maps.newHashMap();
        map.put("OutTradeNo", code);
        map.put("body", form.getPayName());
        map.put("fee", String.valueOf(form.getPayPrice()));
        map.put("tradeType", EnumType.TradeType.WECHAT_JSAPI.getType());
        map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));
        // 获取统一下单后的参数
        try {
            R<Object> payR = WxPayBusiness.Init().h5UnifiedOrder(request, map, shAppId, shMchId, shMchKey, notifyUrl);
            return payR;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.fail("收银台-微信付款H5支付，发起支付异常");
    }

    @Deprecated
    @ApiOperation(value = "支付宝扫码支付")
    @GetMapping(value = "/getAliQrcode", produces = "text/html; charset=UTF-8")
    public R<Object> getAliQrcode(
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) throws Exception {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        // 判断订单状态
        R<Object> r = judgeOrder(form);
        if (R.isError(r))
            return r;

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.ALIPAY_QR.getType());

        // 支付宝H5支付
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setOutTradeNo(code);
        model.setSubject(form.getPayName());
        model.setTotalAmount(String.valueOf(form.getPayPrice()));
        model.setTimeoutExpress("30m");
        model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));

        String resultStr = AliPayApi.tradePrecreatePay(model, AlipayConfig.getScanNotifyUrl(notifyUrl), AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY);
        JSONObject jsonObject = JSONObject.parseObject(resultStr);
        JSONObject response = jsonObject.getJSONObject("alipay_trade_precreate_response");
        Integer responseCode = response.getInteger("code");
        if (responseCode == 10000) {
            String qrCode = response.getString("qr_code");
            if (StringUtils.isNotBlank(qrCode)) {
                return R.ok(qrCode);
            }
        } else {
            String sub_msg = response.getString("sub_msg");
            return R.fail(sub_msg);
        }
        return R.fail("获取支付宝付款二维码失败");
    }

    @ApiOperation(value = "支付宝电脑网站支付")
    @GetMapping(value = "/getAliPagePay", produces = "text/html; charset=UTF-8")
    public void getAliPagePay(
            HttpServletResponse response,
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) throws Exception {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        // 判断订单状态
        if (form == null) throw new DescribeException("订单获取失败");
        if (form.getStatus().equals(0)) throw new DescribeException("订单已被取消");
        if (form.getStatus().equals(1)) throw new DescribeException("订单已被支付");
        if (form.getPayPrice() <= 0) throw new DescribeException("订单的付款金额错误");
        if (DateUtil.getNowDatetime().getTime() > form.getExpireTime().getTime())
            throw new DescribeException("订单有效已过期");

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.ALIPAY_PC.getType());

        // 支付宝电脑网站支付
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(code);
        model.setSubject(form.getPayName());
        model.setTotalAmount(String.valueOf(form.getPayPrice()));
        model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));

        AliPayApi.pagePay(response, model, "", AlipayConfig.getNotifyUrl(notifyUrl), AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY);
    }

    @ApiOperation(value = "支付宝H5支付")
    @GetMapping(value = "/getAliWebPay", produces = "text/html; charset=UTF-8")
    public void getAliWebPay(
            HttpServletResponse response,
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) throws Exception {
        // 查询充值订单流水号
        CooperPayOrder form = cooperPayOrderService.getByOrderUid(orderUid);
        // 判断订单状态
        if (form == null) throw new DescribeException("订单获取失败");
        if (form.getStatus().equals(0)) throw new DescribeException("订单已被取消");
        if (form.getStatus().equals(1)) throw new DescribeException("订单已被支付");
        if (form.getPayPrice() <= 0) throw new DescribeException("订单的付款金额错误");
        if (DateUtil.getNowDatetime().getTime() > form.getExpireTime().getTime())
            throw new DescribeException("订单有效已过期");

        // 更新订单的订单号和支付渠道（防止更改微信支付时订单号重复）
        String code = KitUtil.getGoodsCode();
        cooperPayOrderService.updateCodeAndPayChannelCode(orderUid, code, EnumType.PayChannelCode.ALIPAY_H5.getType());

        // 支付宝H5支付
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(code);
        model.setSubject(form.getPayName());
        model.setTotalAmount(String.valueOf(form.getPayPrice()));
        model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.HZDD.getType()));

        AliPayApi.wapPay(response, model, "", AlipayConfig.getNotifyUrl(notifyUrl), AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY);
    }

    @ApiOperation(value = "获取订单的支付状态")
    @PostMapping(value = "/getPayStatus", produces = "application/json; charset=UTF-8")
    public R<Object> getPayStatus(
            @RequestParam(value = "orderUid") @ApiParam(value = "订单uid") String orderUid
    ) {
        Integer status = cooperPayOrderService.getOrderStatus(orderUid);
        return R.ok(status);
    }

    /**
     * 判断订单状态
     */
    private R<Object> judgeOrder(CooperPayOrder order) {
        if (order == null) return R.fail("订单获取失败");
        if (order.getStatus().equals(0)) return R.fail("订单已被取消");
        if (order.getStatus().equals(1)) return R.fail("订单已被支付");
        if (order.getPayPrice() <= 0) return R.fail("订单的付款金额错误");
        if (DateUtil.getNowDatetime().getTime() > order.getExpireTime().getTime())
            return R.fail("订单有效已过期");
        return R.ok();
    }
}